package cn.sc.summer.gateway.exception;

import com.alibaba.fastjson.JSONObject;
import cn.sc.summer.constant.model.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.lang.NonNull;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 网关的异常处理类
 */
@Slf4j
@Configuration
public class GlobalExceptionConfiguration implements ErrorWebExceptionHandler {

    @Override
    @NonNull
    public Mono<Void> handle(@NonNull ServerWebExchange exchange,@NonNull Throwable exception) {
        ServerHttpResponse response = exchange.getResponse();
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON_UTF8);
        //response是否结束（如果有多个异常处理时候，这个response对象一定要是没提交的状态）
        if (response.isCommitted()) {
            return Mono.error(exception);
        }
        if (exception instanceof CommonException) {
            response.setStatusCode(HttpStatus.FORBIDDEN);
        } else {
            response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
        }

        log.error("Throwable interface: {}, message: {}", exchange.getRequest().getPath(), exception.getMessage());
        exception.printStackTrace();

        //4.设置响应内容
        return response
                .writeWith(Mono.fromSupplier(() -> {
                    try {
                        DataBufferFactory bufferFactory = response.bufferFactory();
                        return bufferFactory.wrap(JSONObject.toJSONBytes(Result.fail(exception.getMessage())));
                    } catch (Exception e) {
                        e.printStackTrace();
                        return null;
                    }
                }));
    }
}

